//Joonas Koskinen
//Pro Gradu Työ
//Jyväskylän Yliopisto

//! cInfo - class is an interface for the numerical methods, differential equations and potential wells in this software.

#ifndef CINFO
#define CINFO

//#include "gnuplot_i.h"
//---------------------------
//-Potentials-
#include "potentials/cPot.h"
#include "potentials/cHO.h"
#include "potentials/csqinf.h"
#include "potentials/cYukawa.h"
#include "potentials/csqfinite.h"
#include "potentials/cGaussattr.h"
#include "potentials/csqsemiinf.h"
#include "potentials/cHydrogen.h"
#include "potentials/cCoupledsq.h"
#include "potentials/cLennardJones.h"
#include "potentials/cHOdipole.h"
#include "potentials/cMorse.h"
#include "potentials/cSqNsFinite.h"
#include "potentials/tripleGaussian.h"
//---------------------------

//---------------------------
//-Numerical methods-
#include "numericals/cNum.h"
#include "numericals/cRKN.h"
#include "numericals/cEuler.h"
#include "numericals/cRK4.h"
#include "numericals/ciEuler.h"
#include "numericals/cNumerov.h"
#include "numericals/cRKF23.h"
#include "numericals/cRKF45.h"
#include "numericals/cDOPRI.h"
#include "numericals/NumerovMatrix.h"
#include "numericals/NumerovMatrixSparse.h"
#include "numericals/VerletMatrix.h"
//---------------------------
//---------------------------
//-Differential equations-
#include "diffeq/cDY.h"
#include "diffeq/cSchrodinger.h"
//---------------------------
#include "util/cLevy.h"
#include "util/convert.h"
//#include "util/cFilter.h"
#include <vector>
#include <algorithm>
#include <string>
#include <iostream>
#include <cmath>

//----------------------
//--MathGL library includes
#include <mgl2/mgl.h>

using namespace std;

class cInfo {
	vector<Num *> numerical;
	vector<cPot *> potential;
	vector<cDY *> DY;
//	Gnuplot gp;
	int activepotential;
	int activemethod;
	int activeDE;

        bool calcNextEigen;
        bool saveImage;
        
//--MathGL declarations
        mglGraph potGraph, solGraph, solpotGraph;
        mglData potDataX, potDataY, solDataX, solDataY;
        //unsigned char * buf;
public:
	cInfo();
	~cInfo();
	//**cPot metodit
	//! Set the size of the box the potential is embedded in
	void set_universe(double value);
	//! Set the depth of the potential
	void set_depth(double value);
	//! Set the width of the potential
	void set_width(double value);
	//! Set the "spring constant" for the potential
	void set_k(double value);
	//! Set the active potential, i.e. potential that is used in the calculations
	void set_activePotential(unsigned int value);
	//! Set the left wall x-coord of the potential
	void set_pot_left(double value);
	//! Set the right wall x-coord of the potential
	void set_pot_right(double value);
	//! Init attributes
	void init();
	//! Return potential depth
	double get_depth();
	//! Return potential widht
	double get_width();
	//! Return k, "spring constant"
	double get_k();
	//! Return potential left wall x-coord
	double get_pot_left();
	//! Return potential right wall x-coord
	double get_pot_right();

	double get_min_energy();

	//! Return result vector x
	vector<double> get_x();
	//! Return result vector y
	vector<double> get_y();
	//! Return the index of the currentyl active potential
	unsigned int get_activePotential();
	//! Return the name of the potential
	string get_pot_name();
	//! Return the name of the potential at index value
	string get_pot_name(unsigned int value);
	//! Return the number of potentials currently available in the program
	unsigned int get_pot_count();

	//! Move potential to the right or left (+/-)
	void move_potential(double value);

//	void setUsingFilter(bool value);
//	bool isUsingFilter() const;
//
//	vector<double> getFilterData() const;
//
//	void setFilterStep(double value);
//	double getFilterStep() const;

	//**cPot metodit


	//**cDY metodit
	//! Set the active differential equation
	void set_activeDE(unsigned int value);
	//! Set the initial value for energy
	void set_E(double value);
	//! Return energy
	double get_E();
	//! Return currently active differential equation
	int get_activeDE();
	//! Return the number of differential equations currently available in the program
	unsigned int get_DE_count();
	//! Return the name of the differential equation
	string get_DE_name();
	//**cDY metodit

	//**cNum metodit
	//! Return the number of solvers currently available in the program
	unsigned int get_solver_count();
	//! Return the name of the active solver
	string get_solver_name();
	//! Return the name of the solver at index value
	string get_solver_name(unsigned int value);
	//! Return the gluepoint tolerance
	double get_f_e_tol();
	//! Return the index of the active solver
	unsigned int get_activeMethod();
	//! Set the active method
	void set_activeMethod(unsigned int value);
	//! Set the gluepoint tolerance
	void set_f_e_tol(double value);
	//! Set the step size
	void set_step(double value);
	//! Find the next eigenvalue using currently active potential, solver and differential equation
	void find_next_eigenfunction(double E_step=0.1, unsigned int break_value=1000);

	//! Calculate the solution with current active potential, solver, differential equation using set energy.
	void calculate();
	//! Find the number of zeros of the resultant vector
	int find_zeros();
	//**cNum metodit
        
        //!Write result to file
        void writeResults();
        //! Append a string to a file
        void appendToFile(string filename, string value);
	//! Write vector to disk
	void write_disk(string filename, vector<double> arr);
	//! Write a gnuplot formatted file of two vectors y against x.
	void write_gnuplot_file(string filename, vector<double> x, vector<double> y);
	//! Plot vectors x against y tuo a png file.
	void gp_plotxy(vector<double> x, vector<double> y, string title, string style, string labelx, string labely,string filename="result.png", string terminal="x11");
	//! Return vector that describes the active potential well
	void get_potential_form(vector<double> &x, vector<double> &y, double step=0.1);
	//! Return the i:th component of the result vektor x.
	double get_xi(unsigned int i);
	//! Return the i:th component of the result vektor y.
	double get_yi(unsigned int i);
	//! Return the size of vector x
	unsigned int sizeof_x();
	//! Return the size of vector y
	unsigned int sizeof_y();
	//! Return the value of potential at x
	double get_poty(double x);
	//! Return quantum number l
	unsigned int get_l();
	//! Set quantum number l
	void set_l(unsigned int value);

	bool isResultLimitSet();

	void useResultLimit(bool value);
    void setResultLimit(double value);

    double getResultLimit();

    unsigned int getLimitIndexBegin();
    unsigned int getLimitIndexEnd();

    void limitResultVector();
    void setCalcNextEigen(bool calcNextEigen);
    bool isCalcNextEigen() const;

    //Next nodecount for automatic solver
    void setNextNode(unsigned int value);
    unsigned int getNextNode();

    //Setters and getters for E_step
    void setE_step(double value);
    double getE_step();
    
    void mglInit();
    void plotPotential(int width, int height);
    void plotSolution(int width, int height);
    void plotSolutionAndPotential(int width, int height);
    void plotMultiple(int width, int height, vector<int> n, bool displayAxis);
    
    void getPotentialPlotQt(unsigned char * & pot_buf);
    
    void getSolutionPlotQt(unsigned char * & sol_buf);

    int getSolutionPlotWidth();
    int getSolutionPlotHeight();
    
    int getPotentialPlotWidth();
    int getPotentialPlotHeight();

    void setEigenIndex(int eigenIndex);
    int getEigenIndex() const;    
    
    double getEigenValue(int n);
    void getEigenVector(int n);
    void setSaveImage(bool saveImage);
    bool isSaveImage() const;
    
    double getStep();
};

#endif
